Zum Hauptinhalt springen
Version: 1.5

Datenstruktur Feld, Suchen & Sortieren

IN-SA TB #018/024–027


Datenstruktur Feld (Array / Liste)

Was ist ein Feld?

Die Datenstruktur Feld (in anderen Sprachen: Array / Feld) speichert eine beliebige Anzahl von Elementen, die im Speicher aneinandergefügt werden.

Elemente werden über einen Index angesprochen (beginnt bei 0).

Index:  [0]  [1]  [2]  [3]  [4]  [5]  [6]
Werte: 1 2 5 9 1 7 11

Wichtige Operationen in Python

x = [1, 2, 5, 3, 9, 7, 1, 18, 3, 27, 5, 12, 18]

# Länge
len(x) # Anzahl der Elemente

# Einzelnes Element abrufen
print(x[0]) # → 1
print(x[6]) # → 3

# Über alle Elemente iterieren
for i in x:
print(i)

# Mit Index iterieren
for i in range(len(x)):
print(x[i])

# Bedingung prüfen
for i in range(len(x)):
if x[i] == 7:
print("super", i)

# Element hinzufügen
x.append(11) # fügt 11 ans Ende an

# Element an Index ändern
x[4] = 67

# Mit Zufallswerten befüllen
import random
for i in range(11):
x[i] = random.randint(0, 10) # Zufallswert 0–10

Suchen

① Sequentielle / Lineare Suche

Jedes Element des Feldes wird mit dem Gesuchten verglichen, bis es gefunden oder sein Nichtvorhandensein bestätigt wird.

FallVergleiche
Best Case1 Element
Average Casen/2 Elemente
Worst Casen Elemente

Bei großen Datensätzen kann die Suche entsprechend lange dauern.

def linSearch(n, liste):
i = 0
while i <= len(liste) - 1:
if liste[i] == n:
return i
i += 1
return -1

② Binäre Suche

Die binäre Suche halbiert bei jedem Schritt den Suchbereich. Das Feld muss sortiert sein!

Prinzip

Feld: [3, 4, 8, 10, 12, 13, 16, 18, 67]
0 1 2 3 4 5 6 7 8

Gesucht: x = 16

Schritt 1: m = (0+8)/2 = 4 → Feld[4] = 12 → 12 < 16 → l = m+1 = 5
Schritt 2: m = (5+8)/2 = 6 → Feld[6] = 16 → GEFUNDEN!

Implementierung (rekursiv)

def binSearch(x, liste, l, r):
if l > r:
return -1 # nicht gefunden
m = (l + r) // 2
if liste[m] == x:
return m
elif liste[m] < x:
return binSearch(x, liste, m + 1, r)
else:
return binSearch(x, liste, l, m - 1)

Wichtigste Unterschiede: Lineare vs. Binäre Suche

Lineare SucheBinäre Suche
VoraussetzungKein sortiertes Feld nötigFeld muss sortiert sein
Aufwand (Worst Case)O(n)O(log n)
PrinzipElement für ElementHalbieren des Suchbereichs

Sortieren

① Selection Sort (Auswahlsortieren)

Prinzip: Finde in jedem Durchlauf das Minimum des noch unsortierten Teils und tausche es an die richtige Stelle.

def selectionSort(feld):
for i in range(len(feld)):
mindex = i
for j in range(i, len(feld)):
if feld[mindex] > feld[j]:
mindex = j
# Tausch
hilf = feld[i]
feld[i] = feld[mindex]
feld[mindex] = hilf
FallLaufzeit
Best CaseO(n²)
Average CaseO(n²)
Worst CaseO(n²)

② Insertion Sort (Einfügesortieren)

Prinzip: Füge jedes Element an die richtige Stelle im bereits sortierten Teil ein.

def insertionSort(feld):
for i in range(len(feld)):
for j in range(i, 0, -1):
if feld[j] < feld[j - 1]:
hilf = feld[j]
feld[j] = feld[j - 1]
feld[j - 1] = hilf
FallLaufzeit
Best CaseO(n)
Average CaseO(n²)
Worst CaseO(n²)

③ Bubble Sort

Prinzip: Vergleiche benachbarte Elemente und tausche sie, wenn sie in der falschen Reihenfolge sind. Große Elemente „blubbern" nach oben.

def bubbleSort(feld):
for i in range(len(feld)):
getauscht = False
for j in range(len(feld) - 1 - i):
if feld[j] > feld[j + 1]:
hilf = feld[j]
feld[j] = feld[j + 1]
feld[j + 1] = hilf
getauscht = True
if not getauscht:
break # Optimierung: kein Tausch → fertig
FallLaufzeit
Best CaseO(n) – dank Optimierung
Average CaseO(n²)
Worst CaseO(n²)

Der Aufwand von Algorithmen (Komplexität)

Der Aufwand eines Algorithmus ist abhängig von der Anzahl der Ausführungen von Befehlen (in Abhängigkeit von der Eingabegröße n).

O-Notation (Landau-Notation)

BezeichnungNotationBeispiel
Konstante LaufzeitO(1)x = x + 1 (einmal)
Lineare LaufzeitO(n)eine Schleife über n
Quadratische LaufzeitO(n²)zwei verschachtelte Schleifen über n

Beispiele

x = x + 1                          # t(n) = 1        → O(1)

for i in range(5):
x = x + 1 # t(n) = 5 → O(1) (konstant)

for i in range(n):
x = x + 1 # t(n) = n → O(n)

for i in range(5):
for j in range(6):
x = x + 1 # t(n) = 30 → O(1) (konstant)

for i in range(n):
for j in range(n):
x = x + 1 # t(n) = n² → O(n²)

# Kombination:
x = x + 1
for i in range(n):
x = x + 1 # t(n) = 1 + n + n² → O(n²) (dominanter Term)
for j in range(n):
for k in range(n):
x = x + 1

Vergleich für n = 10, 100, 1000, 1 000 000

nO(n²) = n²
10100
10010.000
1.0001.000.000
1.000.00010¹²

Bei quadratischem Aufwand wächst die Laufzeit extrem schnell!


Vergleich der Sortieralgorithmen

AlgorithmusBest CaseAverage CaseWorst CaseStabil?
Selection SortO(n²)O(n²)O(n²)
Insertion SortO(n)O(n²)O(n²)
Bubble SortO(n)O(n²)O(n²)
Merge SortO(n log n)O(n log n)O(n log n)
QuicksortO(n log n)O(n log n)O(n²)

Ein Sortieralgorithmus heißt stabil, wenn gleichwertige Elemente ihre ursprüngliche Reihenfolge behalten.